package com.youngjun.common.security.filter;

import com.youngjun.common.security.exception.CustomAuthenticationException;
import com.youngjun.common.security.service.CaptchaService;
import com.youngjun.common.util.SpringUtils;
import com.youngjun.common.util.JsonUtils;
import com.youngjun.common.util.PropUtils;
import com.youngjun.common.util.StringUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestBodyReaderAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private static final Log LOG = LogFactory.getLog(RequestBodyReaderAuthenticationFilter.class);

    private static final String ERROR_MESSAGE = "Something went wrong while parsing /login request body";

    private final static String JWT_AUTH_PROVIDE = "jwt";

    public RequestBodyReaderAuthenticationFilter() {
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String requestBody;
        try {
            requestBody = IOUtils.toString(request.getReader());
            AuthenticationRequest authenticationRequest = JsonUtils.getObjectMapper().readValue(requestBody, AuthenticationRequest.class);

            String provider = PropUtils.get("security.auth.provider");
            if(!JWT_AUTH_PROVIDE.equals(provider)){
                // 添加验证码校验
                if(StringUtils.isEmpty(authenticationRequest.getCaptcha())){
                    throw new IOException("验证码有误");
                }
                if (!SpringUtils.getBean(CaptchaService.class).validateCode(authenticationRequest.getCaptcha())){
                    throw new IOException("验证码有误");
                }
            }

            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword());

            request.setAttribute("username", authenticationRequest.getUsername());
            // Allow subclasses to set the "details" property
            setDetails(request, token);

            return this.getAuthenticationManager().authenticate(token);
        }catch (BadCredentialsException e){
            LOG.error(ERROR_MESSAGE, e);
            throw new CustomAuthenticationException("用户名或密码错误",e);
        }catch (IOException e) {
            LOG.error(ERROR_MESSAGE, e);
            throw new CustomAuthenticationException("验证码错误", e);
        }
    }
}